package com.baomidou.springmvc.interceptor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;  

import javax.servlet.http.HttpServletRequest;  
import javax.servlet.http.HttpServletResponse;  

import org.springframework.web.method.HandlerMethod;  
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import net.sf.json.JSONObject;  


/**
 * 
 * @author hewei
 * @ClassName: SameUrlDataInterceptor
 * @Copyright beauty_tech
 * @date 2018年6月3日 下午10:48:20
 * @description  一个用户 相同url 同时提交 相同数据 验证 
 * 主要通过 session中保存到的url 和 请求参数。如果和上次相同，则是重复提交表单 
 */
public class SameUrlDataInterceptor  extends HandlerInterceptorAdapter{  
	static List<String> list = new ArrayList<String>(1000);
	@Override  
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {  
		if (handler instanceof HandlerMethod) {  
			String contextPath = request.getContextPath();
			HandlerMethod handlerMethod = (HandlerMethod) handler;  
			Method method = handlerMethod.getMethod();  
			SameUrlData annotation = method.getAnnotation(SameUrlData.class);  
			if (annotation != null) {  
				if(repeatDataValidator(request)){
					response.setCharacterEncoding("UTF-8");
					response.setContentType("application/json; charset=utf-8");
					// 重定向到另外一个请求（app端无法解析html）
					response.sendRedirect(contextPath+"/user/repeat");
					return false; 
				}//如果重复相同数据  
				else {
					return true;
				}  

			}  
		} else {  
			return super.preHandle(request, response, handler);  
		}
		return true;  
	}  
	/** 
	 * 验证同一个url数据是否相同提交  ,相同返回true 
	 * @param httpServletRequest 
	 * @return 
	 */  
	public boolean repeatDataValidator(HttpServletRequest httpServletRequest)  
	{  	
		String params=JSONObject.fromObject((httpServletRequest.getParameterMap())).toString();
	//        String params=JsonMapper.toJsonString(httpServletRequest.getParameterMap());  
	String url=httpServletRequest.getRequestURI();  
	Map<String,String> map=new HashMap<String,String>();  
	map.put(url, params);  
	String nowUrlParams=map.toString();//  

	//Object preUrlParams=httpServletRequest.getSession().getAttribute("repeatData");
	int flag = -1;
	if(list.size() <= 1000){
		flag = list.indexOf(nowUrlParams);
	}else{
		//在列表长度很小的情况下(eg:10或100个元素)，可以放心的使用这两种方法。但如果列表很大(eg:10M个元素)，
		//那么选择clear还是removeAll会对你java应用的性能造成巨大的影响。甚至有时，在列表过大的情况下，重置会耗费许多时间，那么重新创建一个新的列表比将老的列表重置要好。
		list.clear();
		list = null;
		System.gc();
		list = new ArrayList<String>(1000);
	}
	
	
	if(flag < 0)//如果上一个数据为null,表示还没有访问页面  
	{  
		//httpServletRequest.getSession().setAttribute("repeatData", nowUrlParams);  
		list.add(nowUrlParams);
		return false;  
	}  
	else//否则，已经访问过页面  
	{  
		if(flag >= 0)//如果上次url+数据和本次url+数据相同，则表示重复添加数据  
		{  

			return true;  
		}  
		else//如果上次 url+数据 和本次url加数据不同，则不是重复提交  
		{  
			//httpServletRequest.getSession().setAttribute("repeatData", nowUrlParams);  
			list.add(nowUrlParams);
			return false;  
		}  

	}  
	}  

}  
